# ~*~ coding: utf-8 ~*~
import os
import re
import time
import subprocess
from flask import current_app

from apps.tasks.models import Script
from apps.tasks.utils import TeeObj, gen_log_absolute_path, gen_log_relative_path


def exec_script(script_id, history):
    """
    执行一个脚本文件
    :param script_id: 脚本对象的ID
    :param history: 固定参数
    :return:
    """
    script = Script.query.get(script_id)

    # 生产执行的脚本
    script_full_path = os.path.join(
        current_app.config.get('TASKS_BASE').rstrip('/'),  # script_path
        '{}.{}'.format(script.id, script.get_ext_name())    # script_name
    )
    with open(script_full_path, 'w+', encoding='utf-8') as f:
        f.write(script.content)

    # 脚本执行，并将结果写到日志中
    log_name = '{}_{}.log'.format(history.id, time.strftime('%Y%m%d%H%M%S', time.localtime()))
    log_absolute_path = gen_log_absolute_path(log_name)
    log_relative_path = gen_log_relative_path(log_name)
    with open(log_absolute_path, 'w+', encoding='utf-8', buffering=1) as f:
        tee = TeeObj(f)
        # -u: Force stdin, stdout and stderr to be totally unbuffered.
        with subprocess.Popen('{} -u {}'.format(script.language, script_full_path),
                              shell=True,
                              bufsize=1,
                              stdout=tee,
                              stderr=tee
                              ) as process:
            current_app.logger.info('Current process pid is {}'.format(process.pid))
            history.log_path = log_relative_path
            history.process_id = process.pid
            history.update()
            process.wait()

    # 需要在日志中获取脚本执行的结果
    try:
        with open(log_absolute_path, 'r+', encoding='utf-8') as f:
            text = f.read()
            response = re.findall("""\{'data': '(.*)', 'is_success': (.*)\}""", text)[0]
        result = {'data': response[0], 'is_success': True if eval(response[1]) else False}
    except IndexError:  # 异常终止, 比如进程被killed
        result = {'data': 'Terminated', 'is_success': 0}

    return result
